#pragma once

#include <assert.h>
#include "../Global References/EngineResources.h"
#include "../Global References/Globals.h"
#include "../Global References/VectorContainer.h"
#include "../Global References/BaseObject.h"

#define MAX_DEBUG_LINES 128

class gui_panel;
class Engine;

struct camera
{
	D3DXVECTOR3 eyePos;			// where the camera is located in world space
	D3DXVECTOR3	lookAt;			// where the camera is looking at in world space
	D3DXVECTOR3 upVector;		// which lastXDir the camera considers "up"

	camera() : eyePos(0.0f, 0.0f, -130.0f), lookAt(0.0f, 0.0f, 0.0f), upVector(0.0f, 1.0f, 0.0f) {}
	camera(D3DXVECTOR3 eyePos, D3DXVECTOR3 lookAt, D3DXVECTOR3 upVector) : eyePos(eyePos), lookAt(lookAt), upVector(upVector) {}
};

struct debugLine
{
	D3DXVECTOR2	startVertex, endVertex;

	debugLine() {  
		startVertex.x = startVertex.y = 0.0f;
		endVertex = startVertex;
	}

	void set(D3DXVECTOR2 start, D3DXVECTOR2 end) {
		startVertex = start;
		endVertex = end;
	}

	void setStart(D3DXVECTOR2 start) { startVertex = start; }
	void setEnd(D3DXVECTOR2 end)	 { endVertex = end; }
};

/*************************************************************************************************************************************************************/
/* The Graphics class will be responsible for and be able to handle drawing 2D sprites and 3D meshes to the screen
/* The process for doing this will be to access the Engine's drawlist manager and using it to draw everything to the screen
/* Graphics will have no duties other than managing drawing objects to the screen, therefore things like sound, input, game logic should *never* go here
/* This module should only ever be called indirectly through the Base Engine, never on its own
/*
/* -Michael Alstad
/*************************************************************************************************************************************************************/
class Graphics
{
private:
	/* Declaration of Member variables of Graphics */
	IDirect3DDevice9*		m_pD3DDevice;				// the main drawing device
	ID3DXFont*				m_pFontManager;				// for drawing text to the screen
	ID3DXSprite*			m_pSpriteManager;			// for drawing sprites to the screen
	ID3DXLine*				m_pLineManager;				// for drawing basic lines
	D3DPRESENT_PARAMETERS	m_D3Dpp;					// presentation parameters to be setup in Init()
	HWND					m_hWnd;						// a copy of hWnd from main for initialization
	int						m_iHeight, m_iWidth;		// a copy of the main window's dimensions
	bool					m_bInitialized;				// indicates whether Init() has been called previously
	bool					m_bInitFailed;				// indicates whether Init() returned false
	bool					m_bWindowed;				// fullscreen = false

	/* Matrices used for rendering each frame */
	D3DXMATRIX				m_worldMat;
	D3DXMATRIX				m_transMat;
	D3DXMATRIX				m_rotationMat;
	D3DXMATRIX				m_scaleMat;
	D3DXMATRIX				m_matPerspective;
	D3DXMATRIX				m_matView;
	D3DVIEWPORT9			m_viewPort;

	/* Variables used for the debug lines */
	D3DXVECTOR2				m_DebugLines[MAX_DEBUG_LINES];
	int						m_iNumLines;
	bool					m_bLineStarted;

	Vector<GameAsset>		m_vAssetLists[ASSET_TYPES];

	camera					m_Camera;
	D3DLIGHT9				m_WorldLight;
	D3DLIGHT9				m_PlayerLight;
	D3DMATERIAL9			m_DefaultMat;

	/* Used for modifying an Object's color*/
	D3DCOLOR				m_ObjectColor;


	/* Conversion functions */
	D3DXVECTOR3	ConvertScreenToWorld(D3DXVECTOR2);
	void ConvertWorldToScreen(D3DXVECTOR3);
	D3DXVECTOR4 Transform(D3DXVECTOR3, D3DXMATRIX);

	/* Sub-functions of the main Init() */
	bool InitDevice(HWND hWnd);
	bool InitManagers();
	bool InitCamera();
	bool InitLight();
	bool InitMaterials();

	/* Sub-function of Render */
	void DrawWorld();
	void DrawObject(BaseObject* pObj);
	void Draw3D(Vector3D a_trans, Vector3D a_rot, Vector3D a_scale, GameAsset asset);
	D3DXMATRIX CreateWorldMatrix(Vector3D a_trans, Vector3D a_rot, Vector3D a_scale);
	void DrawGUI(gui_panel* guiObj, GameAsset asset);

	/* Sub-functions used to load from files */
	void LoadMeshFromFile(const char* cszFileName, ID3DXMesh* & pMesh);
	void LoadTextureFromFile(const char* cszFileName, color* cKey, IDirect3DTexture9* & pTex);

	void SetPlayerLight(float x, float y, float z);
	void SetPlayerLight(Vector3D pos)			{ SetPlayerLight(pos.x, pos.y, pos.z); }

	/* Sub-functions related to the camera */
	void RefreshCamera()						{ InitCamera(); }
	void SetCameraPos (Vector3D pos)			{ SetCameraPos(pos.x, pos.y, pos.z); }
	void SetCameraPos (float x, float y, float z);
	void SetCameraView(Vector3D view)			{ SetCameraView(view.x, view.y, view.z); }
	void SetCameraView(float x, float y, float z);


public:
	/* Prototypes for public functions */
	Graphics();											// unlike previous iterations, this engine will not be a singleton
	bool Init(HWND hWnd);

	Vector2D	AddAsset(const char* meshLoc, const char* textureLoc, color* cKey, RECT* pBlitData, e_AssetType assetList);		// for 3d meshes
	Vector2D	AddAsset(const char* textureLoc, color* cKey, RECT* pBlitData, e_AssetType assetList);							// for 2d sprites
	void		ChangeAssetColorKey(Vector2D assetLoc, color RGBval);																				// for an already existing asset
	bool		RemoveAsset(Vector2D assetLoc);
	Vector2D	GetAssetDimensions(Vector2D assetLoc);
	Vector<GameAsset>* GetAssetList()	{return  m_vAssetLists;}
	void Update();
	void Render();
	void Release();
	~Graphics();



};

#include "Engine.h"